package com.lxl.message;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;
import com.lxl.config.ServiceFunction;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.util.*;

import static com.lxl.message.TemplateStringUtils.*;

//模板文件对应的数据
public class TemplateData {

    protected Map<String, Object> dataMatrix;
    protected List<Map> dataMapTree;
    private MsgStatus status;//消息状态
    protected int arrayLength;

    public TemplateData(MsgStatus status, String msgContent, TemplateMeta templateMeta){
        dataMatrix = new LinkedHashMap<>();
        this.dataMapTree = new LinkedList<>();
        this.status = status;

        if ("json".equals(templateMeta.type)){
            buildMatrixFromJson(msgContent, templateMeta.structure);
        }else if ("xml".equals(templateMeta.type)){
            buildMatrixFromXml(msgContent, templateMeta.structure);
        }
    }

    //创建矩阵，为每列创建边界值
    private void buildMatrixFromJson(String kettleResult, TemplateStructure structure){
        JSONObject kettleJson = JSONObject.parseObject(kettleResult);
        jsonRecurve(kettleJson, structure);
    }

    private void jsonRecurve(JSONObject jsonObject, TemplateStructure structure){
        if (structure.hasObject()){
            for (Map.Entry<String, String> entry : structure.getObject().entrySet()){
                //("In object:[ " + entry.getKey() + "," + entry.getValue() + " ]");
                if (isKeyTag(entry.getKey())){
                    List<String> temp = (List<String>) JSONPath.eval(jsonObject, entry.getValue());
                    dataMatrix.put(entry.getKey(), temp);
                    arrayLength = temp.size();
                } else if (isSysTag(entry.getKey())){
                    String valueStr = getBracketedStr(entry.getValue());
                    if (!valueStr.toUpperCase().equals("TYPE")){
                        dataMatrix.put(entry.getKey(), ServiceFunction.valueOf(valueStr).getFunc()+"");
                    }else{
                        dataMatrix.put(entry.getKey(), status.getIndex()+"");
                    }
                }
            }
        }

        if (structure.hasArray()){
            for (Map.Entry<String, TemplateStructure> entry : structure.getArray().entrySet()){
                //("In array: " + entry.getKey());
                jsonRecurve(jsonObject, entry.getValue());
               //("Out array: " + entry.getKey());
            }
        }
    }

    private void buildMatrixFromXml(String kettleResult, TemplateStructure structure){

        try {
            Document document = DocumentHelper.parseText(kettleResult);
            xmlRecurve(document, structure);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

    private void xmlRecurve(Document document, TemplateStructure structure){
        if (structure.hasObject()){
            for (Map.Entry<String, String> entry : structure.getObject().entrySet()){
                //("In object:[ " + entry.getKey() + "," + entry.getValue() + " ]");
                if (isKeyTag(entry.getKey())){
                    List<String> temp = elements2Strings(document.selectNodes(entry.getValue()));
                    dataMatrix.put(entry.getKey(), temp);
                    arrayLength = temp.size();
                } else if (isSysTag(entry.getKey())){
                    if (!"#TYPE#".equals(entry.getValue())){
                        dataMatrix.put(entry.getKey(), ServiceFunction.valueOf(getBracketedStr(entry.getValue())).getFunc()+"");
                    }else{
                        dataMatrix.put(entry.getKey(), status.getIndex()+"");
                    }
                }
            }
        }

        if (structure.hasArray()){
            for (Map.Entry<String, TemplateStructure> entry : structure.getArray().entrySet()){
                //("In array: " + entry.getKey());
                xmlRecurve(document, entry.getValue());
                //("Out array: " + entry.getKey());
            }
        }
    }

    private static List<String> elements2Strings(List<Element> eles){
        List<String> strList = new LinkedList<>();
        for (Element ele : eles){
            strList.add(ele.getText());
        }

        return strList;
    }
}
